/*学生选修课程可用学生类和课程类之间的关联关系来建模。设计并实现这两个类以及它们的关联关系，要求如下：
（1）学生的属性有姓名和学号；
（2）课程的属性有课程名、编号和学分；
（3）通过课程类能知道选修了该课程的所有学生；
（4）通过学生类能知道自己选修了哪些课程。
编写测试程序，模拟学生选课的操作，选课完成后，打印某门课程的学生名单，对某位学生，统计选修课程的总学分数。
提示：使用前向引用声明，因为涉及到类的交叉引用。*/
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>//find???
using namespace std;
class CCourse;
//学生类    
class CStudent{  
    string name;  
    unsigned id;  
    vector<CCourse*> cs;  
public:  
    CStudent(string nm, unsigned sid):name(nm),id(sid){}; 
    ~CStudent()=default;  
    unsigned getId() const{return id;};  
    const string& getName() const{return name;};  
    
    void takeCourse(CCourse* c);  
    void quitCourse(CCourse* c);  
   
    string printCourses() const;  
    int getTotalCredits() const;  
};  
//课程类  
class CCourse{  
    string name;  
    unsigned id;  
    int credit;  
    vector<CStudent*> stu;  
public:  
    CCourse(string nm, unsigned cid, int crdt):name(nm),id(cid),credit(crdt){};  
    ~CCourse()=default;  
    
    int getCredit(){return credit;};  
    unsigned getId(){return id;};  
    const string& getName(){return name;};  
    
    string printStudents() const;  
    void take(CStudent* s);  
    void quit(CStudent* s);  
}; 
void CStudent::takeCourse(CCourse* c)
{
    auto it=find(cs.begin(),cs.end(),c);
    
   /*if(it!=cs.end())//课程中含有c，接下来将学生加入课程c
   { c->take(this); return;}
  这种理解其实是错的，说明我没有理解交叉类的意义 */
   
   if(it!=cs.end())
   {return ;}      //stu的course中含有c
    //如果课程中不含c
    cs.push_back(c);
    c->take(this);//同时课程中加入学生姓名
    

}
void CStudent::quitCourse(CCourse*c)//为啥参数是CCourse
//CCourse *c表示c是一个CCourse类的对象？
{ 
    auto it=find(cs.begin(),cs.end(),c);
    if(it!=cs.end())
    //找到了
    cs.erase(it);
    return;
}
//STL库中的语法，emplace_back等等都怎么用
string CStudent::printCourses()const
{
  
  string courseList="";//建立一个空字符串
  for(auto it=cs.begin();it!=cs.end();++it)
  {
     courseList+=(*it)->getName();//访问接口
     if((it+1)!=cs.end())
     courseList+=",";
  }
  return courseList;
}
int CStudent::getTotalCredits()const
{
  int totalCredits=0;
  for(auto it=cs.begin();it!=cs.end();++it)
  {
    //totalcredits+=(*it)->credit;  //credit是不可访问的，必须通过接口实现
    totalCredits+=(*it)->getCredit();//(*it)的含义
  }
  return totalCredits;
}
 string CCourse::printStudents() const
 {
   string stuList="";
    for(auto it=stu.begin();it!=stu.end();++it)
    {
       stuList+=(*it)->getName();
       if((it+1)!=stu.end())
       stuList+=",";
    }
    return stuList;
 } 
    void CCourse::take(CStudent* s)
    {
        auto it=find(stu.begin(),stu.end(),s);
        if(it!=stu.end())
        //说明找到了
        return ;
        else stu.push_back(s);
        //s.takeCourse(this);

    }

    void CCourse::quit(CStudent* s)
      {
        auto it=find(stu.begin(),stu.end(),s);
        if(it!=stu.end())
        stu.erase(it);
        return ;
    }
   int main()
{
    CCourse c1("Java", 101, 3);
    CCourse c2("C++", 201, 3);
    CCourse c3("Data Structure", 102, 4);
    CCourse c4("OS", 302, 3);
    CCourse c5("Software Engineering", 301, 4);

    CStudent s1("Li Lin", 118001);
    CStudent s2("Liu Na", 119003);
    CStudent s3("Zhao Mei", 118011);
    CStudent s4("Zhang Wei", 119006);
    CStudent s5("Sun Yang", 118015);
    CStudent s6("Meng Hui", 118023);

    s1.takeCourse(&c1);
    s1.takeCourse(&c3);
    s2.takeCourse(&c4);
    s2.takeCourse(&c5);

    s3.takeCourse(&c1);
    s3.takeCourse(&c2);
    s3.takeCourse(&c3);
    s3.takeCourse(&c4);
    s3.takeCourse(&c5);

    cout<<"Student ";
    cout << s1.getName() << ":" << s1.printCourses() << "," << s1.getTotalCredits()<<endl;

    cout<<"Student ";
    cout << s3.getName() << ":" << s3.printCourses() << "," << s3.getTotalCredits()<<endl;

    cout<<"Course ";
    cout << c1.getName() << ":" << c1.printStudents()<<endl;

    cout<<"Course ";
    cout << c2.getName() << ":" << c2.printStudents()<<endl;

    cout<<"Course ";
    cout << c3.getName() << ":" << c3.printStudents()<<endl;

    cout<<"Course ";
    cout << c4.getName() << ":" << c4.printStudents()<<endl;

    cout<<"Course ";
    cout << c5.getName() << ":" << c5.printStudents()<<endl;

    s3.quitCourse(&c1);
    cout<<"Student ";
    cout << s3.getName() << ":" << s3.printCourses() << s3.getTotalCredits()<<endl;

    cout<<"Course ";
    cout<<c1.getName() << ":" << c1.printStudents()<<endl;

    return 0;
}